package com.example.bbs.dao;

import com.example.bbs.annotation.ColumnAnnotation;
import com.example.bbs.annotation.TableAnnotation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @auther: zhangxin
 * @Description:
 */
public class BaseDao {

    private static final Logger LOGGER = LogManager.getLogger(BaseDao.class);

    private static  String URL, USERNAME, PWD, DRIVER_NAME;
    private static DataSource dataSource;

    public static void init(DataSource dataSource){
         BaseDao.dataSource = dataSource;
    }

    static {
        //加载配置文件
        loadProperties();
        try {
            Class.forName(DRIVER_NAME);
        } catch (ClassNotFoundException e) {
            LOGGER.error(e);
            System.exit(1);
        }
    }

    private static void loadProperties() {
        //读取配置文件
        Properties properties = new Properties();
        //加载文件
        try {
            properties.load(BaseDao.class.getResourceAsStream("/mysql.properties"));
            //读取文件内容
            URL = properties.getProperty("url");
            if (URL == null) {
                throw new Exception("配置文件异常:没有找到url配置");
            }

            USERNAME = properties.getProperty("user_name");
            if (USERNAME == null) {
                throw new Exception("配置文件异常:没有找到user_name配置");
            }

            PWD = properties.getProperty("user_pwd");
            if (PWD == null) {
                throw new Exception("配置文件异常:没有找到user_pwd配置");
            }

            DRIVER_NAME = properties.getProperty("driver_name");
            if (DRIVER_NAME == null) {
                throw new Exception("配置文件异常:没有找到driver_name配置");
            }

        } catch (Exception e) {
            LOGGER.error(e);
            System.exit(1);
        }
    }

    protected Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }



    /**
     * 通用的增删改方法
     *
     * @param sql
     * @param args
     * @return
     */
    public boolean executeUpdate(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        int lastId = -1;
        try {
            //2.创建连接对象
            connection = getConnection();
            //3.创建预处理执行对象
            statement = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            //填坑
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }
            //执行
            int count = statement.executeUpdate();
            resultSet = statement.getGeneratedKeys();
            if(resultSet.next()){
                lastId = resultSet.getInt(1);
                System.out.println("该ID:" + lastId);
            }
            return count > 0;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(connection, statement, null);
        }
        return false;
    }

    public List<Object> executeQuery(CallBack callBack,String sql, Object... args){
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Object> lists = new ArrayList<>();
        try {
            //2.创建连接对象
            connection = getConnection();
            //3.创建预处理执行对象
            statement = connection.prepareStatement(sql);
            //填坑
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }
            //执行
            resultSet = statement.executeQuery();
            lists = callBack.doResultSet(resultSet);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(connection, statement, null);
        }
        return lists;
    }

    /**
     * 关闭连接
     * @param connection
     * @param statement
     * @param resultSet
     */
    protected void close(Connection connection, Statement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }


    private TableBean getBeanInfo(Object bean) throws IllegalAccessException {
        TableBean tableBean = new TableBean();
        // 属性名 ==> 列名(标识自增长列,主键)
        tableBean.columns  = new ArrayList<ColumnBean>();
        //反射获取注解信息
        //1.获取Class
        Class clz = bean.getClass();
        //2.获取注解信息
        TableAnnotation annotation = (TableAnnotation) clz.getAnnotation(TableAnnotation.class);
        //类 ==> 表名
        tableBean.tableName = clz.getSimpleName();
        //如果没有设置表名,与类名相同
        if(annotation != null && annotation.tableName().length() != 0){
            tableBean.tableName = annotation.tableName();
        }
        //获取字段上的注解
        Field[] fields = clz.getDeclaredFields();
        for (Field field : fields) {
            //设置访问权限
            field.setAccessible(true);
            //获取字段的值
            Object val = field.get(bean);
            //获取字段上的ColumnAnnotation注解
            ColumnAnnotation ano = field.getAnnotation(ColumnAnnotation.class);
            if (ano == null) {
                //如果没有注解,说明属性名与列名相同
                tableBean.columns.add(new ColumnBean(field.getName(),val));
                continue;
            }
            //是否忽略
            if (ano.ignore()){
                continue;
            }
            //判断是否设置了列名
            String columnName = ano.column().length()==0? field.getName():ano.column();
            tableBean.columns.add(new ColumnBean(columnName,val,ano.isPK(),ano.isAutoIncrement()));
        }

        return tableBean;
    }

    class TableBean{
        String tableName;
        List<ColumnBean> columns;
    }
    /**
     * 描述类中属性与表中列信息的关系
     */
    class ColumnBean {
        //列名
        String columnName;
        //列的值
        Object value;
        //是否是主键
        boolean isPK;
        //是否自增
        boolean isAuto;

        public ColumnBean(String columnName, Object val) {
            this.columnName = columnName;
            this.value = val;
        }

        public ColumnBean(String columnName, Object value, boolean isPK, boolean isAuto) {
            this.columnName = columnName;
            this.value = value;
            this.isPK = isPK;
            this.isAuto = isAuto;
        }
    }

}
